home *** CD-ROM | disk | FTP | other *** search
/ Magnum One / Magnum One (Mid-American Digital) (Disc Manufacturing).iso / d13 / phantz.arc / PHANT4.Z / PHANT4
Text File  |  1991-06-06  |  60KB  |  2,208 lines

  1.  
  2. : ---------CUT HERE---------
  3. : This is a shar archive.  Extract with sh, not csh.
  4. : The rest of this file will extract:
  5. :  macros.h phantdefs.h setup.c misc.c oldplayer.h
  6. echo x - macros.h
  7. sed 's/^X//' > macros.h << '!EOR!'
  8. X/*
  9. X * macros.h - macro definitions for Phantasia
  10. X */
  11. X
  12. X#define ROLL(BASE,INTERVAL)    floor((BASE) + (INTERVAL) * random())
  13. X#define SGN(X)        ((X) < 0 ? -1 : 1)
  14. X#define CIRCLE(X, Y)    floor(distance(X, 0.0, Y, 0.0) / 125.0 + 1)
  15. X#define MAX(A, B)    ((A) > (B) ? (A) : (B))
  16. X#define MIN(A, B)    ((A) < (B) ? (A) : (B))
  17. X#define ILLCMD()    mvaddstr(5, 0, Illcmd)
  18. X#define MAXMOVE()    (Player.p_level * 1.5 + 1)
  19. X#define ILLMOVE()    mvaddstr(5, 0, Illmove)
  20. X#define ILLSPELL()    mvaddstr(5, 0, Illspell)
  21. X#define NOMANA()    mvaddstr(5, 0, Nomana)
  22. X#define SOMEBETTER()    addstr(Somebetter)
  23. X#define NOBETTER()    mvaddstr(17, 0, Nobetter)
  24. !EOR!
  25. echo x - phantdefs.h
  26. sed 's/^X//' > phantdefs.h << '!EOR!'
  27. X/*
  28. X * phantdefs.h - important constants for Phantasia
  29. X */
  30. X
  31. X/* ring constants */
  32. X#define R_NONE        0        /* no ring */
  33. X#define R_NAZREG    1        /* regular Nazgul ring (expires) */
  34. X#define R_DLREG        2        /* regular Dark Lord ring (does not expire) */
  35. X#define R_BAD        3        /* bad ring */
  36. X#define R_SPOILED     4        /* ring which has gone bad */
  37. X
  38. X/* status constants */
  39. X#define    S_NOTUSED    0        /* record not in use */
  40. X#define S_OFF        1        /* not playing */
  41. X#define S_PLAYING    2        /* playing - nothing else */
  42. X#define S_CLOAKED    3        /* playing - cloaked */
  43. X#define S_INBATTLE    4        /* playing - in battle */
  44. X#define S_MONSTER    5        /* playing - fighting monster */
  45. X#define    S_TRADING    6        /* playing - at a trading post */
  46. X#define    S_HUNGUP    7        /* error occured with character */
  47. X
  48. X/* tampered constants */
  49. X#define T_OFF        0        /* nothing */
  50. X#define T_NRGVOID    1        /* hit an energy void */
  51. X#define T_GRAIL        2        /* landed on the holy grail */
  52. X#define T_TRANSPORT    3        /* transported by king */
  53. X#define T_BESTOW    4        /* gold bestowed by king */
  54. X#define T_CURSED    5        /* cursed by king */
  55. X#define T_MONSTER    6        /* monster lobbed by valar */
  56. X#define T_BLESSED    7        /* blessed by valar */
  57. X#define T_RELOCATE    8        /* moved by valar */
  58. X#define T_HEAL        9        /* healed by valar */
  59. X#define T_VAPORIZED    10        /* vaporized by wizard */
  60. X#define T_EXVALAR    11        /* no longer valar */
  61. X
  62. X/* inter-terminal battle status constants */
  63. X#define    I_OFF        0        /* nothing */
  64. X#define    I_RAN        1        /* ran away */
  65. X#define    I_STUCK        2        /* tried to run unsuccessfully */
  66. X#define    I_BLEWIT    3        /* tried to luckout unsuccessfully */
  67. X#define    I_KILLED    4        /* killed foe */
  68. X
  69. X/* constants for altering coordinates */
  70. X#define    A_SPECIFIC    0        /* coordinates specified */
  71. X#define    A_FORCED    1        /* coordinates specified, ignore Beyond */
  72. X#define A_NEAR        2        /* coordinates not specified, move near */
  73. X#define A_FAR        3        /* coordinates not specified, move far */
  74. X
  75. X/* constants for character types */
  76. X#define C_MAGIC        0        /* magic user */
  77. X#define C_FIGHTER    1        /* fighter */
  78. X#define C_ELF        2        /* elf */
  79. X#define C_DWARF        3        /* dwarf */
  80. X#define C_HALFLING    4        /* halfling */
  81. X#define C_EXPER        5        /* experimento */
  82. X#define C_SUPER        6        /* super being */
  83. X
  84. X/* constants for special character types */
  85. X#define SC_NONE        0        /* not a special character */
  86. X#define    SC_KING        1        /* king */
  87. X#define SC_COUNCIL    2        /* council of the wise */
  88. X#define SC_VALAR    3        /* valar */
  89. X#define SC_EXVALAR    4        /* ex-valar */
  90. X
  91. X/* special monster constants */
  92. X#define    SM_NONE        0        /* nothing special */
  93. X#define    SM_UNICORN    1        /* unicorn */
  94. X#define    SM_MODNAR    2        /* Modnar */
  95. X#define    SM_MIMIC    3        /* mimic */
  96. X#define    SM_DARKLORD    4        /* Dark Lord */
  97. X#define    SM_LEANAN    5        /* Leanan-Sidhe */
  98. X#define    SM_SARUMAN    6        /* Saruman */
  99. X#define    SM_THAUMATURG    7        /* thaumaturgist */
  100. X#define    SM_BALROG    8        /* balrog */
  101. X#define    SM_VORTEX    9        /* vortex */
  102. X#define SM_NAZGUL    10        /* nazgul */
  103. X#define    SM_TIAMAT    11        /* Tiamat */
  104. X#define    SM_KOBOLD    12        /* kobold */
  105. X#define    SM_SHELOB    13        /* Shelob */
  106. X#define    SM_FAERIES    14        /* assorted faeries */
  107. X#define    SM_LAMPREY    15        /* lamprey */
  108. X#define    SM_SHRIEKER    16        /* shrieker */
  109. X#define    SM_BONNACON    17        /* bonnacon */
  110. X#define    SM_SMEAGOL    18        /* Smeagol */
  111. X#define    SM_SUCCUBUS    19        /* succubus */
  112. X#define    SM_CERBERUS    20        /* Cerberus */
  113. X#define    SM_UNGOLIANT    21        /* Ungoliant */
  114. X#define    SM_JABBERWOCK    22        /* jabberwock */
  115. X#define    SM_MORGOTH    23        /* Morgoth */
  116. X#define    SM_TROLL    24        /* troll */
  117. X#define    SM_WRAITH    25        /* wraith */
  118. X
  119. X/* constants for spells */
  120. X#define    ML_ALLORNOTHING    0.0        /* magic level for 'all or nothing' */
  121. X#define MM_ALLORNOTHING    1.0        /* mana used for 'all or nothing' */
  122. X#define    ML_MAGICBOLT    5.0        /* magic level for 'magic bolt' */
  123. X#define    ML_FORCEFIELD    15.0        /* magic level for 'force field' */
  124. X#define    MM_FORCEFIELD    30.0        /* mana used for 'force field' */
  125. X#define    ML_XFORM    25.0        /* magic level for 'transform' */
  126. X#define    MM_XFORM    50.0        /* mana used for 'transform' */
  127. X#define    ML_INCRMIGHT    35.0        /* magic level for 'increase might' */
  128. X#define    MM_INCRMIGHT    75.0        /* mana used for 'increase might' */
  129. X#define    ML_INVISIBLE    45.0        /* magic level for 'invisibility' */
  130. X#define    MM_INVISIBLE    90.0        /* mana used for 'invisibility' */
  131. X#define    ML_XPORT    60.0        /* magic level for 'transport' */
  132. X#define    MM_XPORT    125.0        /* mana used for 'transport' */
  133. X#define    ML_PARALYZE    75.0        /* magic level for 'paralyze' */
  134. X#define    MM_PARALYZE    150.0        /* mana used for 'paralyze' */
  135. X#define    MM_SPECIFY    1000.0        /* mana used for 'specify' */
  136. X#define ML_CLOAK    20.0        /* magic level for 'cloak' */
  137. X#define    MEL_CLOAK    7.0        /* experience level for 'cloak' */
  138. X#define    MM_CLOAK    35.0        /* mana used for 'cloak' */
  139. X#define    ML_TELEPORT    40.0        /* magic level for 'teleport' */
  140. X#define    MEL_TELEPORT    12.0        /* experience level for 'teleport' */
  141. X#define    MM_INTERVENE    1000.0        /* mana used to 'intervene' */
  142. X
  143. X/* some miscellaneous constants */
  144. X#define SZ_DATABUF    100        /* size of input buffer */
  145. X#define    SZ_PLAYERSTRUCT    sizeof(struct player) /* size of player structure */
  146. X#define    SZ_VOIDSTRUCT    sizeof(struct energyvoid) /* size of energy void struct */
  147. X#define    SZ_SCORESTRUCT    sizeof(struct scoreboard) /* size of score board entry */
  148. X#define    SZ_MONSTERSTRUCT sizeof(struct monster) /* size of monster structure */
  149. X#define    SZ_NAME        21        /* size of player name (incl. trailing nul) */
  150. X#define    SZ_PASSWORD    9        /* size of password (incl. trailing nul) */
  151. X#define    SZ_LOGIN    9        /* size of login (incl. trailing nul) */
  152. X
  153. X#define N_DAYSOLD    21        /* number of days old for purge */
  154. X#define N_AGE        500        /* age to degenerate ratio */
  155. X#define    N_GEMVALUE    (1000.0)    /* number of gold pieces to gem ratio */
  156. X#define    N_TAXAMOUNT    (7.0)        /* tax percent */
  157. X#ifdef OK_TO_PLAY
  158. X#define    N_MAXUSERS    30        /* max. number of users allowed on system */
  159. X#endif
  160. X
  161. X#define    D_BEYOND    (1.1e6)        /* distance to beyond point of no return */
  162. X#define D_EXPER        (2000.0)    /* distance experimentos are allowed */
  163. X
  164. X#define    CH_MARKDELETE    '\001'        /* used to alter name of deleted players */
  165. X#define    CH_KILL        '\030'        /* kill character (ctrl-X) */
  166. X#define    CH_ERASE    '\010'        /* erase character (ctrl-H) */
  167. X#define    CH_NEWLINE    '\n'        /* newline */
  168. X#define    CH_REDRAW    '\014'        /* redraw screen character (ctrl-L) */
  169. !EOR!
  170. echo x - setup.c
  171. sed 's/^X//' > setup.c << '!EOR!'
  172. X/*
  173. X * setup.c - set up all files for Phantasia
  174. X */
  175. X#include "include.h"
  176. X#include <sys/types.h>
  177. X#include <sys/stat.h>
  178. X/* */
  179. X/************************************************************************
  180. X/
  181. X/ FUNCTION NAME: main()
  182. X/
  183. X/ FUNCTION: setup files for Phantasia 3.3.2
  184. X/
  185. X/ AUTHOR: E. A. Estes, 12/4/85
  186. X/
  187. X/ ARGUMENTS: none
  188. X/
  189. X/ RETURN VALUE: none
  190. X/
  191. X/ MODULES CALLED: time(), exit(), stat(), Error(), creat(), close(), fopen(), 
  192. X/    fgets(), floor(), srand(), umask(), random(), strcpy(), getuid(), 
  193. X/    unlink(), fwrite(), fclose(), sscanf(), printf(), strlen(), fprintf()
  194. X/
  195. X/ GLOBAL INPUTS: Peoplefile[], Curmonster, _iob[], Databuf[], *Monstfp, 
  196. X/    Lastdead[], Goldfile[], Voidfile[], Motdfile[], Messfile[], Scorefile[], 
  197. X/    Enemyfile[], Monstfile[], Enrgyvoid
  198. X/
  199. X/ GLOBAL OUTPUTS: Curmonster, Databuf[], *Monstfp, Enrgyvoid
  200. X/
  201. X/ DESCRIPTION: 
  202. X/
  203. X/    This program tries to verify the parameters specified in
  204. X/    the Makefile.
  205. X/
  206. X/    Create all necessary files.  Note that nothing needs to be
  207. X/    put in these files.
  208. X/    Also, the monster binary data base is created here.
  209. X/
  210. X/************************************************************************/
  211. X
  212. Xmain()
  213. X{
  214. XFILE    *fp;            /* for opening files */
  215. Xstruct stat    fbuf;        /* for getting files statistics */
  216. Xregister char    **filename;    /* for pointing to file names */
  217. Xregister int    fd;        /* file descriptor */
  218. Xstatic char *files[] =        /* all files to create */
  219. X    {
  220. X    Monstfile,
  221. X    Peoplefile,
  222. X    Messfile,
  223. X    Lastdead,
  224. X    Motdfile,
  225. X    Goldfile,
  226. X    Voidfile,
  227. X    Scorefile,
  228. X#ifdef ENEMY
  229. X    Enemyfile,
  230. X#endif
  231. X    (char *) NULL
  232. X    };
  233. X
  234. X    srand((unsigned) time((long *) NULL));    /* prime random numbers */
  235. X
  236. X    umask(077);                /* only owner can read/write created files */
  237. X
  238. X    if (getuid() != UID)
  239. X    fprintf(stderr, "Warning: UID (%d) is not equal to current uid.\n", UID);
  240. X
  241. X    /* check Phantasia destination directory */
  242. X    if (stat(DEST", &fbuf) < 0)
  243. X    /* not found */
  244. X    {
  245. X    Error("Cannot stat %s.\n", DEST");
  246. X    exit(1);
  247. X    /*NOTREACHED*/
  248. X    }
  249. X
  250. X    if ((fbuf.st_mode & S_IFDIR) == 0)
  251. X    /* not a directory */
  252. X    Error("%s is not a directory.\n", DEST");
  253. X    /*NOTREACHED*/
  254. X
  255. X    /* try to create data files */
  256. X    filename = &files[0];
  257. X    while (*filename != NULL)
  258. X    /* create each file */
  259. X    {
  260. X    if (stat(*filename, &fbuf) == 0)
  261. X        /* file exists; remove it */
  262. X        {
  263. X        if (*filename == Peoplefile)
  264. X        /* do not reset character file if it already exists */
  265. X        {
  266. X        ++filename;
  267. X        continue;
  268. X        }
  269. X
  270. X        if (unlink(*filename) < 0)
  271. X        Error("Cannot unlink %s.\n", *filename);
  272. X        /*NOTREACHED*/
  273. X        }
  274. X
  275. X    if ((fd = creat(*filename, 0600)) < 0)
  276. X        Error("Cannot create %s.\n", *filename);
  277. X        /*NOTREACHED*/
  278. X
  279. X    close(fd);            /* close newly created file */
  280. X
  281. X    ++filename;            /* process next file */
  282. X    }
  283. X
  284. X    /* put holy grail info into energy void file */
  285. X    Enrgyvoid.ev_active = TRUE;
  286. X    Enrgyvoid.ev_x = ROLL(-1.0e6, 2.0e6);
  287. X    Enrgyvoid.ev_y = ROLL(-1.0e6, 2.0e6);
  288. X    if ((fp = fopen(Voidfile, "w")) == NULL)
  289. X    Error("Cannot update %s.\n", Voidfile);
  290. X    else
  291. X    {
  292. X    fwrite(&Enrgyvoid, SZ_VOIDSTRUCT, 1, fp);
  293. X    fclose(fp);
  294. X    }
  295. X
  296. X    /* create binary monster data base */
  297. X    if ((Monstfp = fopen(Monstfile, "w")) == NULL)
  298. X    Error("Cannot update %s.\n", Monstfile);
  299. X    else
  300. X    {
  301. X    if ((fp = fopen("monsters.asc", "r")) == NULL)
  302. X        {
  303. X        fclose(Monstfp);
  304. X        Error("cannot open %s to create monster database.\n", "monsters.asc");
  305. X        }
  306. X    else
  307. X        {
  308. X        Curmonster.m_o_strength =
  309. X        Curmonster.m_o_speed =
  310. X        Curmonster.m_maxspeed =
  311. X        Curmonster.m_o_energy =
  312. X        Curmonster.m_melee =
  313. X        Curmonster.m_skirmish = 0.0;
  314. X
  315. X        while (fgets(Databuf, SZ_DATABUF, fp) != NULL)
  316. X        /* read in text file, convert to binary */
  317. X        {
  318. X        sscanf(&Databuf[24], "%F%F%F%F%F%d%d%F",
  319. X            &Curmonster.m_strength, &Curmonster.m_brains,
  320. X            &Curmonster.m_speed, &Curmonster.m_energy,
  321. X            &Curmonster.m_experience, &Curmonster.m_treasuretype,
  322. X            &Curmonster.m_type, &Curmonster.m_flock);
  323. X        Databuf[24] = '\0';
  324. X        strcpy(Curmonster.m_name, Databuf);
  325. X        fwrite((char *) &Curmonster, SZ_MONSTERSTRUCT, 1, Monstfp);
  326. X        }
  327. X        fclose(fp);
  328. X        fclose(Monstfp);
  329. X        }
  330. X    }
  331. X
  332. X    /* write to motd file */
  333. X    printf("One line 'motd' ? ");
  334. X    if (fgets(Databuf, SZ_DATABUF, stdin) == NULL)
  335. X    Databuf[0] = '\0';
  336. X    if ((fp = fopen(Motdfile, "w")) == NULL)
  337. X    Error("Cannot update %s.\n", Motdfile);
  338. X    else
  339. X    {
  340. X    fwrite(Databuf, sizeof(char), strlen(Databuf), fp);
  341. X    fclose(fp);
  342. X    }
  343. X
  344. X    /* report compile-time options */
  345. X    printf("Compiled options:\n\n");
  346. X    printf("Phantasia destination directory:  %s\n", DEST");
  347. X    printf("Wizard:  %s   UID:  %d\n", WIZARD, UID);
  348. X
  349. X#ifdef OK_TO_PLAY
  350. X    printf("Restricted playing enabled.\n");
  351. X#else
  352. X    printf("Playing unrestricted.\n");
  353. X#endif
  354. X
  355. X#ifdef ENEMY
  356. X    printf("Enemy list enabled.\n");
  357. X#else
  358. X    printf("Enemy list disabled.\n");
  359. X#endif
  360. X
  361. X#ifdef SHELL
  362. X    printf("Shell escapes enabled.  Default shell:  %s\n", SHELL);
  363. X#else
  364. X    printf("Shell escapes disabled.\n");
  365. X#endif
  366. X
  367. X#ifdef BSD41
  368. X    printf("Compiled for BSD 4.1\n");
  369. X#endif
  370. X
  371. X#ifdef BSD42
  372. X    printf("Compiled for BSD 4.2\n");
  373. X#endif
  374. X
  375. X#ifdef SYS3
  376. X    printf("Compiled for System III\n");
  377. X#endif
  378. X
  379. X#ifdef SYS5
  380. X    printf("Compiled for System V\n");
  381. X#endif
  382. X
  383. X    exit(0);
  384. X    /*NOTREACHED*/
  385. X}
  386. X/* */
  387. X/************************************************************************
  388. X/
  389. X/ FUNCTION NAME: Error()
  390. X/
  391. X/ FUNCTION: print an error message, and exit
  392. X/
  393. X/ AUTHOR: E. A. Estes, 12/4/85
  394. X/
  395. X/ ARGUMENTS:
  396. X/    char *str - format string for printf()
  397. X/    char *file - file which caused error
  398. X/
  399. X/ RETURN VALUE: none
  400. X/
  401. X/ MODULES CALLED: exit(), perror(), fprintf()
  402. X/
  403. X/ GLOBAL INPUTS: _iob[]
  404. X/
  405. X/ GLOBAL OUTPUTS: none
  406. X/
  407. X/ DESCRIPTION:
  408. X/    Print an error message, then exit.
  409. X/
  410. X/************************************************************************/
  411. X
  412. XError(str, file)
  413. Xchar    *str, *file;
  414. X{
  415. X    fprintf(stderr, "Error: ");
  416. X    fprintf(stderr, str, file);
  417. X    perror(file);
  418. X    exit(1);
  419. X    /*NOTREACHED*/
  420. X}
  421. X/* */
  422. X/************************************************************************
  423. X/
  424. X/ FUNCTION NAME: random()
  425. X/
  426. X/ FUNCTION: return a random number
  427. X/
  428. X/ AUTHOR: E. A. Estes, 2/7/86
  429. X/
  430. X/ ARGUMENTS: none
  431. X/
  432. X/ RETURN VALUE: none
  433. X/
  434. X/ MODULES CALLED: rand()
  435. X/
  436. X/ GLOBAL INPUTS: none
  437. X/
  438. X/ GLOBAL OUTPUTS: none
  439. X/
  440. X/ DESCRIPTION: 
  441. X/
  442. X/************************************************************************/
  443. X
  444. Xdouble
  445. Xrandom()
  446. X{
  447. X    if (sizeof(int) != 2)
  448. X    return((double) (rand() & 0x7fff) / 32768.0);
  449. X    else
  450. X    return((double) rand() / 32768.0);
  451. X}
  452. !EOR!
  453. echo x - misc.c
  454. sed 's/^X//' > misc.c << '!EOR!'
  455. X/*
  456. X * misc.c  Phantasia miscellaneous support routines
  457. X */
  458. X
  459. X#include "include.h"
  460. X
  461. X/************************************************************************
  462. X/
  463. X/ FUNCTION NAME: movelevel()
  464. X/
  465. X/ FUNCTION: move player to new level
  466. X/
  467. X/ AUTHOR: E. A. Estes, 12/4/85
  468. X/
  469. X/ ARGUMENTS: none
  470. X/
  471. X/ RETURN VALUE: none
  472. X/
  473. X/ MODULES CALLED: death(), floor(), wmove(), random(), waddstr(), explevel()
  474. X/
  475. X/ GLOBAL INPUTS: Player, *stdscr, *Statptr, Stattable[]
  476. X/
  477. X/ GLOBAL OUTPUTS: Player, Changed
  478. X/
  479. X/ DESCRIPTION:
  480. X/    Use lookup table to increment important statistics when
  481. X/    progressing to new experience level.
  482. X/    Players are rested to maximum as a bonus for making a new
  483. X/    level.
  484. X/    Check for council of wise, and being too big to be king.
  485. X/
  486. X/************************************************************************/
  487. X
  488. Xmovelevel()
  489. X{
  490. Xregister struct charstats    *statptr;    /* for pointing into Stattable */
  491. Xdouble    new;            /* new level */
  492. Xdouble    inc;            /* increment between new and old levels */
  493. X
  494. X    Changed = TRUE;
  495. X
  496. X    if (Player.p_type == C_EXPER)
  497. X    /* roll a type to use for increment */
  498. X    statptr = &Stattable[(int) ROLL(C_MAGIC, C_HALFLING - C_MAGIC + 1)];
  499. X    else
  500. X    statptr = Statptr;
  501. X
  502. X    new = explevel(Player.p_experience);
  503. X    inc = new - Player.p_level;
  504. X    Player.p_level = new;
  505. X
  506. X    /* add increments to statistics */
  507. X    Player.p_strength += statptr->c_strength.increase * inc;
  508. X    Player.p_mana += statptr->c_mana.increase * inc;
  509. X    Player.p_brains += statptr->c_brains.increase * inc;
  510. X    Player.p_magiclvl += statptr->c_magiclvl.increase * inc;
  511. X    Player.p_maxenergy += statptr->c_energy.increase * inc;
  512. X
  513. X    /* rest to maximum upon reaching new level */
  514. X    Player.p_energy = Player.p_maxenergy + Player.p_shield;
  515. X
  516. X    if (Player.p_crowns > 0 && Player.p_level >= 1000.0)
  517. X    /* no longer able to be king -- turn crowns into cash */
  518. X    {
  519. X    Player.p_gold += ((double) Player.p_crowns) * 5000.0;
  520. X    Player.p_crowns = 0;
  521. X    }
  522. X
  523. X    if (Player.p_level >= 3000.0 && Player.p_specialtype < SC_COUNCIL)
  524. X    /* make a member of the council */
  525. X    {
  526. X    mvaddstr(6, 0, "You have made it to the Council of the Wise.\n");
  527. X    addstr("Good Luck on your search for the Holy Grail.\n");
  528. X
  529. X    Player.p_specialtype = SC_COUNCIL;
  530. X
  531. X    /* no rings for council and above */
  532. X    Player.p_ring.ring_type = R_NONE;
  533. X    Player.p_ring.ring_duration = 0;
  534. X
  535. X    Player.p_lives = 3;        /* three extra lives */
  536. X    }
  537. X
  538. X    if (Player.p_level > 9999.0 && Player.p_specialtype != SC_VALAR)
  539. X    death("Old age");
  540. X}
  541. X/* */
  542. X/************************************************************************
  543. X/
  544. X/ FUNCTION NAME: descrlocation()
  545. X/
  546. X/ FUNCTION: return a formatted description of location
  547. X/
  548. X/ AUTHOR: E. A. Estes, 12/4/85
  549. X/
  550. X/ ARGUMENTS:
  551. X/    struct player playerp - pointer to player structure
  552. X/    bool shortflag - set if short form is desired
  553. X/
  554. X/ RETURN VALUE: pointer to string containing result
  555. X/
  556. X/ MODULES CALLED: fabs(), floor(), sprintf(), distance()
  557. X/
  558. X/ GLOBAL INPUTS: Databuf[]
  559. X/
  560. X/ GLOBAL OUTPUTS: none
  561. X/
  562. X/ DESCRIPTION:
  563. X/    Look at coordinates and return an appropriately formatted
  564. X/    string.
  565. X/
  566. X/************************************************************************/
  567. X
  568. Xchar    *
  569. Xdescrlocation(playerp, shortflag)
  570. Xstruct player    *playerp;
  571. Xbool    shortflag;
  572. X{
  573. Xdouble    circle;            /* corresponding circle for coordinates */
  574. Xregister int    quadrant;    /* quandrant of grid */
  575. Xregister char    *label;        /* pointer to place name */
  576. Xstatic char    *nametable[4][4] =   /* names of places */
  577. X    {
  578. X    "Anorien",    "Ithilien",    "Rohan",    "Lorien",
  579. X    "Gondor",    "Mordor",    "Dunland",    "Rovanion",
  580. X    "South Gondor", "Khand",    "Eriador",    "The Iron Hills",
  581. X    "Far Harad",    "Near Harad",    "The Northern Waste", "Rhun"
  582. X    };
  583. X
  584. X    if (playerp->p_specialtype == SC_VALAR)
  585. X    return(" is in Valhala");
  586. X    else if ((circle = CIRCLE(playerp->p_x, playerp->p_y)) >= 1000.0)
  587. X    {
  588. X    if (MAX(fabs(playerp->p_x), fabs(playerp->p_y)) > D_BEYOND)
  589. X        label = "The Point of No Return";
  590. X    else
  591. X        label = "The Ashen Mountains";
  592. X    }
  593. X    else if (circle >= 55)
  594. X    label = "Morannon";
  595. X    else if (circle >= 35)
  596. X    label = "Kennaquahair";
  597. X    else if (circle >= 20)
  598. X    label = "The Dead Marshes";
  599. X    else if (circle >= 9)
  600. X    label = "The Outer Waste";
  601. X    else if (circle >= 5)
  602. X    label = "The Moors Adventurous";
  603. X    else
  604. X    {
  605. X    if (playerp->p_x == 0.0 && playerp->p_y == 0.0)
  606. X        label = "The Lord's Chamber";
  607. X    else
  608. X        {
  609. X        /* this expression is split to prevent compiler loop with some compilers */
  610. X        quadrant = ((playerp->p_x > 0.0) ? 1 : 0);
  611. X        quadrant += ((playerp->p_y >= 0.0) ? 2 : 0);
  612. X        label = nametable[((int) circle) - 1][quadrant];
  613. X        }
  614. X    }
  615. X
  616. X    if (shortflag)
  617. X    sprintf(Databuf, "%.29s", label);
  618. X    else
  619. X    sprintf(Databuf, " is in %s  (%.0f,%.0f)", label, playerp->p_x, playerp->p_y);
  620. X
  621. X    return(Databuf);
  622. X}
  623. X/* */
  624. X/************************************************************************
  625. X/
  626. X/ FUNCTION NAME: tradingpost()
  627. X/
  628. X/ FUNCTION: do trading post stuff
  629. X/
  630. X/ AUTHOR: E. A. Estes, 12/4/85
  631. X/
  632. X/ ARGUMENTS: none
  633. X/
  634. X/ RETURN VALUE: none
  635. X/
  636. X/ MODULES CALLED: writerecord(), adjuststats(), fabs(), more(), sqrt(), 
  637. X/    sleep(), floor(), wmove(), random(), wclear(), printw(), 
  638. X/    altercoordinates(), infloat(), waddstr(), wrefresh(), mvprintw(), getanswer(), 
  639. X/    wclrtoeol(), wclrtobot()
  640. X/
  641. X/ GLOBAL INPUTS: Menu[], Circle, Player, *stdscr, Fileloc, Nobetter[]
  642. X/
  643. X/ GLOBAL OUTPUTS: Player
  644. X/
  645. X/ DESCRIPTION:
  646. X/    Different trading posts have different items.
  647. X/    Merchants cannot be cheated, but they can be dishonest
  648. X/    themselves.
  649. X/
  650. X/    Shields, swords, and quicksilver are not cumulative.  This is
  651. X/    one major area of complaint, but there are two reasons for this:
  652. X/        1) It becomes MUCH too easy to make very large versions
  653. X/           of these items.
  654. X/        2) In the real world, one cannot simply weld two swords
  655. X/           together to make a bigger one.
  656. X/
  657. X/    At one time, it was possible to sell old weapons at half the purchase
  658. X/    price.  This resulted in huge amounts of gold floating around,
  659. X/    and the game lost much of its challenge.
  660. X/
  661. X/    Also, purchasing gems defeats the whole purpose of gold.  Gold
  662. X/    is small change for lower level players.  They really shouldn't
  663. X/    be able to accumulate more than enough gold for a small sword or
  664. X/    a few books.  Higher level players shouldn't even bother to pick
  665. X/    up gold, except maybe to buy mana once in a while.
  666. X/
  667. X/************************************************************************/
  668. X
  669. Xtradingpost()
  670. X{
  671. Xdouble    numitems;    /* number of items to purchase */
  672. Xdouble    cost;        /* cost of purchase */
  673. Xdouble    blessingcost;    /* cost of blessing */
  674. Xint    ch;        /* input */
  675. Xregister int    size;    /* size of the trading post */
  676. Xregister int    loop;    /* loop counter */
  677. Xint    cheat = 0;    /* number of times player has tried to cheat */
  678. Xbool    dishonest = FALSE;/* set when merchant is dishonest */
  679. X
  680. X    Player.p_status = S_TRADING;
  681. X    writerecord(&Player, Fileloc);
  682. X
  683. X    clear();
  684. X    addstr("You are at a trading post. All purchases must be made with gold.");
  685. X
  686. X    size = sqrt(fabs(Player.p_x / 100)) + 1;
  687. X    size = MIN(7, size);
  688. X
  689. X    /* set up cost of blessing */
  690. X    blessingcost = 1000.0 * (Player.p_level + 5.0);
  691. X
  692. X    /* print Menu */
  693. X    move(7, 0);
  694. X    for (loop = 0; loop < size; ++loop)
  695. X    /* print Menu */
  696. X    {
  697. X    if (loop == 6)
  698. X        cost = blessingcost;
  699. X    else
  700. X        cost = Menu[loop].cost;
  701. X    printw("(%d) %-12s: %6.0f\n", loop + 1, Menu[loop].item, cost);
  702. X    }
  703. X
  704. X    mvprintw(5, 0, "L:Leave  P:Purchase  S:Sell Gems ? ");
  705. X
  706. X    for (;;)
  707. X    {
  708. X    adjuststats();    /* truncate any bad values */
  709. X
  710. X    /* print some important statistics */
  711. X    mvprintw(1, 0, "Gold:   %9.0f  Gems:  %9.0f  Level:   %6.0f  Charms: %6d\n",
  712. X        Player.p_gold, Player.p_gems, Player.p_level, Player.p_charms);
  713. X    printw("Shield: %9.0f  Sword: %9.0f  Quicksilver:%3.0f  Blessed: %s\n",
  714. X        Player.p_shield, Player.p_sword, Player.p_quksilver,
  715. X        (Player.p_blessing ? " True" : "False"));
  716. X    printw("Brains: %9.0f  Mana:  %9.0f", Player.p_brains, Player.p_mana);
  717. X
  718. X    move(5, 36);
  719. X    ch = getanswer("LPS", FALSE);
  720. X    move(15, 0);
  721. X    clrtobot();
  722. X    switch(ch)
  723. X        {
  724. X        case 'L':        /* leave */
  725. X        case '\n':
  726. X        altercoordinates(0.0, 0.0, A_NEAR);
  727. X        return;
  728. X
  729. X        case 'P':        /* make purchase */
  730. X        mvaddstr(15, 0, "What what would you like to buy ? ");
  731. X        ch = getanswer(" 1234567", FALSE);
  732. X        move(15, 0);
  733. X        clrtoeol();
  734. X
  735. X        if (ch - '0' > size)
  736. X            addstr("Sorry, this merchant doesn't have that.");
  737. X        else
  738. X            switch (ch)
  739. X            {
  740. X            case '1':
  741. X                printw("Mana is one per %.0f gold piece.  How many do you want (%.0f max) ? ",
  742. X                Menu[0].cost, floor(Player.p_gold / Menu[0].cost));
  743. X                cost = (numitems = floor(infloat())) * Menu[0].cost;
  744. X
  745. X                if (cost > Player.p_gold || numitems < 0)
  746. X                ++cheat;
  747. X                else
  748. X                {
  749. X                Player.p_gold -= cost;
  750. X                if (random() < 0.02)
  751. X                    dishonest = TRUE;
  752. X                else
  753. X                    Player.p_mana += numitems;
  754. X                }
  755. X                break;
  756. X
  757. X            case '2':
  758. X                printw("Shields are %.0f per +1.  How many do you want (%.0f max) ? ",
  759. X                Menu[1].cost, floor(Player.p_gold / Menu[1].cost));
  760. X                cost = (numitems = floor(infloat())) * Menu[1].cost;
  761. X
  762. X                if (numitems == 0.0)
  763. X                break;
  764. X                else if (cost > Player.p_gold || numitems < 0)
  765. X                ++cheat;
  766. X                else if (numitems < Player.p_shield)
  767. X                NOBETTER();
  768. X                else
  769. X                {
  770. X                Player.p_gold -= cost;
  771. X                if (random() < 0.02)
  772. X                    dishonest = TRUE;
  773. X                else
  774. X                    Player.p_shield = numitems;
  775. X                }
  776. X                break;
  777. X
  778. X            case '3':
  779. X                printw("A book costs %.0f gp.  How many do you want (%.0f max) ? ",
  780. X                Menu[2].cost, floor(Player.p_gold / Menu[2].cost));
  781. X                cost = (numitems = floor(infloat())) * Menu[2].cost;
  782. X
  783. X                if (cost > Player.p_gold || numitems < 0)
  784. X                ++cheat;
  785. X                else
  786. X                {
  787. X                Player.p_gold -= cost;
  788. X                if (random() < 0.02)
  789. X                    dishonest = TRUE;
  790. X                else if (random() * numitems > Player.p_level / 10.0
  791. X                    && numitems != 1)
  792. X                    {
  793. X                    printw("\nYou blew your mind!\n");
  794. X                    Player.p_brains /= 5;
  795. X                    }
  796. X                else
  797. X                    Player.p_brains += floor(numitems) * ROLL(20, 8);
  798. X                }
  799. X                break;
  800. X
  801. X            case '4':
  802. X                printw("Swords are %.0f gp per +1.  How many + do you want (%.0f max) ? ",
  803. X                Menu[3].cost, floor(Player.p_gold / Menu[3].cost));
  804. X                cost = (numitems = floor(infloat())) * Menu[3].cost;
  805. X
  806. X                if (numitems == 0.0)
  807. X                break;
  808. X                else if (cost > Player.p_gold || numitems < 0)
  809. X                ++cheat;
  810. X                else if (numitems < Player.p_sword)
  811. X                NOBETTER();
  812. X                else
  813. X                {
  814. X                Player.p_gold -= cost;
  815. X                if (random() < 0.02)
  816. X                    dishonest = TRUE;
  817. X                else
  818. X                    Player.p_sword = numitems;
  819. X                }
  820. X                break;
  821. X
  822. X            case '5':
  823. X                printw("A charm costs %.0f gp.  How many do you want (%.0f max) ? ",
  824. X                Menu[4].cost, floor(Player.p_gold / Menu[4].cost));
  825. X                cost = (numitems = floor(infloat())) * Menu[4].cost;
  826. X
  827. X                if (cost > Player.p_gold || numitems < 0)
  828. X                ++cheat;
  829. X                else
  830. X                {
  831. X                Player.p_gold -= cost;
  832. X                if (random() < 0.02)
  833. X                    dishonest = TRUE;
  834. X                else
  835. X                    Player.p_charms += numitems;
  836. X                }
  837. X                break;
  838. X
  839. X            case '6':
  840. X                printw("Quicksilver is %.0f gp per +1.  How many + do you want (%.0f max) ? ",
  841. X                Menu[5].cost, floor(Player.p_gold / Menu[5].cost));
  842. X                cost = (numitems = floor(infloat())) * Menu[5].cost;
  843. X
  844. X                if (numitems == 0.0)
  845. X                break;
  846. X                else if (cost > Player.p_gold || numitems < 0)
  847. X                ++cheat;
  848. X                else if (numitems < Player.p_quksilver)
  849. X                NOBETTER();
  850. X                else
  851. X                {
  852. X                Player.p_gold -= cost;
  853. X                if (random() < 0.02)
  854. X                    dishonest = TRUE;
  855. X                else
  856. X                    Player.p_quksilver = numitems;
  857. X                }
  858. X                break;
  859. X
  860. X            case '7':
  861. X                if (Player.p_blessing)
  862. X                {
  863. X                addstr("You already have a blessing.");
  864. X                break;
  865. X                }
  866. X
  867. X                printw("A blessing requires a %.0f gp donation.  Still want one ? ", blessingcost);
  868. X                ch = getanswer("NY", FALSE);
  869. X
  870. X                if (ch == 'Y')
  871. X                if (Player.p_gold < blessingcost)
  872. X                    ++cheat;
  873. X                else
  874. X                    {
  875. X                    Player.p_gold -= blessingcost;
  876. X                    if (random() < 0.02)
  877. X                    dishonest = TRUE;
  878. X                    else
  879. X                    Player.p_blessing = TRUE;
  880. X                    }
  881. X                break;
  882. X            }
  883. X        break;
  884. X
  885. X        case 'S':        /* sell gems */
  886. X        mvprintw(15, 0, "A gem is worth %.0f gp.  How many do you want to sell (%.0f max) ? ",
  887. X            (double) N_GEMVALUE, Player.p_gems);
  888. X        numitems = floor(infloat());
  889. X
  890. X        if (numitems > Player.p_gems || numitems < 0)
  891. X            ++cheat;
  892. X        else
  893. X            {
  894. X            Player.p_gems -= numitems;
  895. X            Player.p_gold += numitems * N_GEMVALUE;
  896. X            }
  897. X        }
  898. X
  899. X    if (cheat == 1)
  900. X        mvaddstr(17, 0, "Come on, merchants aren't stupid.  Stop cheating.\n");
  901. X    else if (cheat == 2)
  902. X        {
  903. X        mvaddstr(17, 0, "You had your chance.  This merchant happens to be\n");
  904. X        printw("a %.0f level magic user, and you made %s mad!\n",
  905. X        ROLL(Circle * 20.0, 40.0), (random() < 0.5) ? "him" : "her");
  906. X        altercoordinates(0.0, 0.0, A_FAR);
  907. X        Player.p_energy /= 2.0;
  908. X        ++Player.p_sin;
  909. X        more(23);
  910. X        return;
  911. X        }
  912. X    else if (dishonest)
  913. X        {
  914. X        mvaddstr(17, 0, "The merchant stole your money!");
  915. X        refresh();
  916. X        altercoordinates(Player.p_x - Player.p_x / 10.0,
  917. X        Player.p_y - Player.p_y / 10.0, A_SPECIFIC);
  918. X        sleep(2);
  919. X        return;
  920. X        }
  921. X    }
  922. X}
  923. X/* */
  924. X/************************************************************************
  925. X/
  926. X/ FUNCTION NAME: displaystats()
  927. X/
  928. X/ FUNCTION: print out important player statistics
  929. X/
  930. X/ AUTHOR: E. A. Estes, 12/4/85
  931. X/
  932. X/ ARGUMENTS: none
  933. X/
  934. X/ RETURN VALUE: none
  935. X/
  936. X/ MODULES CALLED: descrstatus(), descrlocation(), mvprintw()
  937. X/
  938. X/ GLOBAL INPUTS: Users, Player
  939. X/
  940. X/ GLOBAL OUTPUTS: none
  941. X/
  942. X/ DESCRIPTION:
  943. X/    Important player statistics are printed on the screen.
  944. X/
  945. X/************************************************************************/
  946. X
  947. Xdisplaystats()
  948. X{
  949. X    mvprintw(0, 0, "%s%s\n", Player.p_name, descrlocation(&Player, FALSE));
  950. X    mvprintw(1, 0, "Level :%7.0f   Energy  :%9.0f(%9.0f)  Mana :%9.0f  Users:%3d\n",
  951. X    Player.p_level, Player.p_energy, Player.p_maxenergy + Player.p_shield,
  952. X    Player.p_mana, Users);
  953. X    mvprintw(2, 0, "Quick :%3.0f(%3.0f)  Strength:%9.0f(%9.0f)  Gold :%9.0f  %s\n",
  954. X    Player.p_speed, Player.p_quickness + Player.p_quksilver, Player.p_might,
  955. X    Player.p_strength + Player.p_sword, Player.p_gold, descrstatus(&Player));
  956. X}
  957. X/* */
  958. X/************************************************************************
  959. X/
  960. X/ FUNCTION NAME: allstatslist()
  961. X/
  962. X/ FUNCTION: show player items
  963. X/
  964. X/ AUTHOR: E. A. Estes, 12/4/85
  965. X/
  966. X/ ARGUMENTS: none
  967. X/
  968. X/ RETURN VALUE: none
  969. X/
  970. X/ MODULES CALLED: mvprintw(), descrtype()
  971. X/
  972. X/ GLOBAL INPUTS: Player
  973. X/
  974. X/ GLOBAL OUTPUTS: none
  975. X/
  976. X/ DESCRIPTION:
  977. X/    Print out some player statistics of lesser importance.
  978. X/
  979. X/************************************************************************/
  980. X
  981. Xallstatslist()
  982. X{
  983. Xstatic    char    *flags[] =    /* to print value of some bools */
  984. X        {
  985. X        "False", 
  986. X        " True"
  987. X        };
  988. X
  989. X    mvprintw( 8,  0, "Type: %s\n",  descrtype(&Player,  FALSE));
  990. X
  991. X    mvprintw(10,  0, "Experience: %9.0f", Player.p_experience);
  992. X    mvprintw(11,  0, "Brains    : %9.0f", Player.p_brains);
  993. X    mvprintw(12,  0, "Magic Lvl : %9.0f", Player.p_magiclvl);
  994. X    mvprintw(13,  0, "Sin       : %9.5f", Player.p_sin);
  995. X    mvprintw(14,  0, "Poison    : %9.5f", Player.p_poison);
  996. X    mvprintw(15,  0, "Gems      : %9.0f", Player.p_gems);
  997. X    mvprintw(16,  0, "Age       : %9d", Player.p_age);
  998. X    mvprintw(10, 40, "Holy Water: %9d", Player.p_holywater);
  999. X    mvprintw(11, 40, "Amulets   : %9d", Player.p_amulets);
  1000. X    mvprintw(12, 40, "Charms    : %9d", Player.p_charms);
  1001. X    mvprintw(13, 40, "Crowns    : %9d", Player.p_crowns);
  1002. X    mvprintw(14, 40, "Shield    : %9.0f", Player.p_shield);
  1003. X    mvprintw(15, 40, "Sword     : %9.0f", Player.p_sword);
  1004. X    mvprintw(16, 40, "Quickslver: %9.0f", Player.p_quksilver);
  1005. X
  1006. X    mvprintw(18,  0, "Blessing: %s   Ring: %s   Virgin: %s   Palantir: %s", 
  1007. X    flags[Player.p_blessing], flags[Player.p_ring.ring_type != R_NONE], 
  1008. X    flags[Player.p_virgin], flags[Player.p_palantir]);
  1009. X}
  1010. X/* */
  1011. X/************************************************************************
  1012. X/
  1013. X/ FUNCTION NAME: descrtype()
  1014. X/
  1015. X/ FUNCTION: return a string specifying player type
  1016. X/
  1017. X/ AUTHOR: E. A. Estes, 12/4/85
  1018. X/
  1019. X/ ARGUMENTS:
  1020. X/    struct player playerp - pointer to structure for player
  1021. X/    bool shortflag - set if short form is desired
  1022. X/
  1023. X/ RETURN VALUE: pointer to string describing player type
  1024. X/
  1025. X/ MODULES CALLED: strcpy()
  1026. X/
  1027. X/ GLOBAL INPUTS: Databuf[]
  1028. X/
  1029. X/ GLOBAL OUTPUTS: Databuf[]
  1030. X/
  1031. X/ DESCRIPTION:
  1032. X/    Return a string describing the player type.
  1033. X/    King, council, valar, supercedes other types.
  1034. X/    The first character of the string is '*' if the player
  1035. X/    has a crown.
  1036. X/    If 'shortflag' is TRUE, return a 3 character string.
  1037. X/
  1038. X/************************************************************************/
  1039. X
  1040. Xchar    *
  1041. Xdescrtype(playerp, shortflag)
  1042. Xstruct player *playerp;
  1043. Xbool    shortflag;
  1044. X{
  1045. Xregister int type;    /* for caluculating result subscript */
  1046. Xstatic char    *results[] =    /* description table */
  1047. X            {
  1048. X            " Magic User", " MU",
  1049. X            " Fighter", " F ",
  1050. X            " Elf", " E ",
  1051. X            " Dwarf", " D ",
  1052. X            " Halfling", " H ",
  1053. X            " Experimento", " EX",
  1054. X            " Super", " S ",
  1055. X            " King", " K ",
  1056. X            " Council of Wise", " CW",
  1057. X            " Ex-Valar", " EV",
  1058. X            " Valar", " V ",
  1059. X            " ? ", " ? "
  1060. X            };
  1061. X
  1062. X    type = playerp->p_type;
  1063. X
  1064. X    switch (playerp->p_specialtype)
  1065. X    {
  1066. X    case SC_NONE:
  1067. X        type = playerp->p_type;
  1068. X        break;
  1069. X
  1070. X    case SC_KING:
  1071. X        type = 7;
  1072. X        break;
  1073. X
  1074. X    case SC_COUNCIL:
  1075. X        type = 8;
  1076. X        break;
  1077. X
  1078. X    case SC_EXVALAR:
  1079. X        type = 9;
  1080. X        break;
  1081. X
  1082. X    case SC_VALAR:
  1083. X        type = 10;
  1084. X        break;
  1085. X    }
  1086. X
  1087. X    type *= 2;        /* calculate offset */
  1088. X
  1089. X    if (type > 20)
  1090. X    /* error */
  1091. X    type = 22;
  1092. X
  1093. X    if (shortflag)
  1094. X    /* use short descriptions */
  1095. X    ++type;
  1096. X
  1097. X    if (playerp->p_crowns > 0)
  1098. X    {
  1099. X    strcpy(Databuf, results[type]);
  1100. X    Databuf[0] = '*';
  1101. X    return(Databuf);
  1102. X    }
  1103. X    else
  1104. X    return(results[type]);
  1105. X}
  1106. X/* */
  1107. X/************************************************************************
  1108. X/
  1109. X/ FUNCTION NAME: findname()
  1110. X/
  1111. X/ FUNCTION: find location in player file of given name
  1112. X/
  1113. X/ AUTHOR: E. A. Estes, 12/4/85
  1114. X/
  1115. X/ ARGUMENTS:
  1116. X/    char *name - name of character to look for
  1117. X/    struct player *playerp - pointer of structure to fill
  1118. X/
  1119. X/ RETURN VALUE: location of player if found, -1 otherwise
  1120. X/
  1121. X/ MODULES CALLED: fread(), fseek(), strcmp()
  1122. X/
  1123. X/ GLOBAL INPUTS: Wizard, *Playersfp
  1124. X/
  1125. X/ GLOBAL OUTPUTS: none
  1126. X/
  1127. X/ DESCRIPTION:
  1128. X/    Search the player file for the player of the given name.
  1129. X/    If player is found, fill structure with player data.
  1130. X/
  1131. X/************************************************************************/
  1132. X
  1133. Xlong
  1134. Xfindname(name, playerp)
  1135. Xregister char    *name;
  1136. Xregister struct player *playerp;
  1137. X{
  1138. Xlong    loc = 0;            /* location in the file */
  1139. X
  1140. X    fseek(Playersfp, 0L, 0);
  1141. X    while (fread((char *) playerp, SZ_PLAYERSTRUCT, 1, Playersfp) == 1)
  1142. X    {
  1143. X    if (strcmp(playerp->p_name, name) == 0)
  1144. X        {
  1145. X        if (playerp->p_status != S_NOTUSED || Wizard)
  1146. X        /* found it */
  1147. X        return(loc);
  1148. X        }
  1149. X    loc += SZ_PLAYERSTRUCT;
  1150. X    }
  1151. X
  1152. X    return(-1);
  1153. X}
  1154. X/* */
  1155. X/************************************************************************
  1156. X/
  1157. X/ FUNCTION NAME: allocrecord()
  1158. X/
  1159. X/ FUNCTION: find space in the player file for a new character
  1160. X/
  1161. X/ AUTHOR: E. A. Estes, 12/4/85
  1162. X/
  1163. X/ ARGUMENTS: none
  1164. X/
  1165. X/ RETURN VALUE: location of free space in file
  1166. X/
  1167. X/ MODULES CALLED: initplayer(), writerecord(), fread(), fseek()
  1168. X/
  1169. X/ GLOBAL INPUTS: Other, *Playersfp
  1170. X/
  1171. X/ GLOBAL OUTPUTS: Player
  1172. X/
  1173. X/ DESCRIPTION:
  1174. X/    Search the player file for an unused entry.  If none are found,
  1175. X/    make one at the end of the file.
  1176. X/
  1177. X/************************************************************************/
  1178. X
  1179. Xlong
  1180. Xallocrecord()
  1181. X{
  1182. Xlong    loc = 0L;        /* location in file */
  1183. X
  1184. X    fseek(Playersfp, 0L, 0);
  1185. X    while (fread((char *) &Other, SZ_PLAYERSTRUCT, 1, Playersfp) == 1)
  1186. X    {
  1187. X    if (Other.p_status == S_NOTUSED)
  1188. X        /* found an empty record */
  1189. X        return(loc);
  1190. X    else
  1191. X        loc += SZ_PLAYERSTRUCT;
  1192. X    }
  1193. X
  1194. X    /* make a new record */
  1195. X    initplayer(&Other);
  1196. X    Player.p_status = S_OFF;
  1197. X    writerecord(&Other, loc);
  1198. X
  1199. X    return(loc);
  1200. X}
  1201. X/* */
  1202. X/************************************************************************
  1203. X/
  1204. X/ FUNCTION NAME: freerecord()
  1205. X/
  1206. X/ FUNCTION: free up a record on the player file
  1207. X/
  1208. X/ AUTHOR: E. A. Estes, 2/7/86
  1209. X/
  1210. X/ ARGUMENTS:
  1211. X/    struct player playerp - pointer to structure to free
  1212. X/    long loc - location in file to free
  1213. X/
  1214. X/ RETURN VALUE: none
  1215. X/
  1216. X/ MODULES CALLED: writerecord()
  1217. X/
  1218. X/ GLOBAL INPUTS: none
  1219. X/
  1220. X/ GLOBAL OUTPUTS: none
  1221. X/
  1222. X/ DESCRIPTION:
  1223. X/    Mark structure as not used, and update player file.
  1224. X/
  1225. X/************************************************************************/
  1226. X
  1227. Xfreerecord(playerp, loc)
  1228. Xstruct player    *playerp;
  1229. Xlong    loc;
  1230. X{
  1231. X    playerp->p_name[0] = CH_MARKDELETE;
  1232. X    playerp->p_status = S_NOTUSED;
  1233. X    writerecord(playerp, loc);
  1234. X}
  1235. X/* */
  1236. X/************************************************************************
  1237. X/
  1238. X/ FUNCTION NAME: leavegame()
  1239. X/
  1240. X/ FUNCTION: leave game
  1241. X/
  1242. X/ AUTHOR: E. A. Estes, 12/4/85
  1243. X/
  1244. X/ ARGUMENTS: none
  1245. X/
  1246. X/ RETURN VALUE: none
  1247. X/
  1248. X/ MODULES CALLED: freerecord(), writerecord(), cleanup()
  1249. X/
  1250. X/ GLOBAL INPUTS: Player, Fileloc
  1251. X/
  1252. X/ GLOBAL OUTPUTS: Player
  1253. X/
  1254. X/ DESCRIPTION:
  1255. X/    Mark player as inactive, and cleanup.
  1256. X/    Do not save players below level 1.
  1257. X/
  1258. X/************************************************************************/
  1259. X
  1260. Xleavegame()
  1261. X{
  1262. X
  1263. X    if (Player.p_level < 1.0)
  1264. X    /* delete character */
  1265. X    freerecord(&Player, Fileloc);
  1266. X    else
  1267. X    {
  1268. X    Player.p_status = S_OFF;
  1269. X    writerecord(&Player, Fileloc);
  1270. X    }
  1271. X
  1272. X    cleanup(TRUE);
  1273. X    /*NOTREACHED*/
  1274. X}
  1275. X/* */
  1276. X/************************************************************************
  1277. X/
  1278. X/ FUNCTION NAME: death()
  1279. X/
  1280. X/ FUNCTION: death routine
  1281. X/
  1282. X/ AUTHOR: E. A. Estes, 12/4/85
  1283. X/
  1284. X/ ARGUMENTS:
  1285. X/    char *how - pointer to string describing cause of death
  1286. X/
  1287. X/ RETURN VALUE: none
  1288. X/
  1289. X/ MODULES CALLED: freerecord(), enterscore(), more(), exit(), fread(), 
  1290. X/    fseek(), execl(), fopen(), floor(), wmove(), random(), wclear(), strcmp(), 
  1291. X/    fwrite(), fflush(), printw(), strcpy(), fclose(), waddstr(), cleanup(), 
  1292. X/    fprintf(), wrefresh(), getanswer(), descrtype()
  1293. X/
  1294. X/ GLOBAL INPUTS: Curmonster, Wizard, Player, *stdscr, Fileloc, *Monstfp, 
  1295. X/    Lastdead[], Gameprog[], Messfile[]
  1296. X/
  1297. X/ GLOBAL OUTPUTS: Player
  1298. X/
  1299. X/ DESCRIPTION:
  1300. X/    Kill off current player.
  1301. X/    Handle rings, and multiple lives.
  1302. X/    Print an appropriate message.
  1303. X/    Update scoreboard, lastdead, and let other players know about
  1304. X/    the demise of their comrade.
  1305. X/
  1306. X/************************************************************************/
  1307. X
  1308. Xdeath(how)
  1309. Xchar    *how;
  1310. X{
  1311. XFILE    *fp;        /* for updating various files */
  1312. Xint    ch;        /* input */
  1313. Xstatic    char    *deathmesg[] =
  1314. X    /* add more messages here, if desired */
  1315. X    {
  1316. X    "You have been wounded beyond repair.  ",
  1317. X    "You have been disemboweled.  ",
  1318. X    "You've been mashed, mauled, and spit upon.  (You're dead.)\n",
  1319. X    "You died!  ",
  1320. X    "You're a complete failure -- you've died!!\n",
  1321. X    "You have been dealt a fatal blow!  "
  1322. X    };
  1323. X
  1324. X    clear();
  1325. X
  1326. X    if (strcmp(how, "Stupidity") != 0)
  1327. X    {
  1328. X    if (Player.p_level > 9999.0)
  1329. X        /* old age */
  1330. X        addstr("Characters must be retired upon reaching level 10000.  Sorry.");
  1331. X    else if (Player.p_lives > 0)
  1332. X        /* extra lives */
  1333. X        {
  1334. X        addstr("You should be more cautious.  You've been killed.\n");
  1335. X        printw("You only have %d more chance(s).\n", --Player.p_lives);
  1336. X        more(3);
  1337. X        Player.p_energy = Player.p_maxenergy;
  1338. X        return;
  1339. X        }
  1340. X    else if (Player.p_specialtype == SC_VALAR)
  1341. X        {
  1342. X        addstr("You had your chances, but Valar aren't totally\n");
  1343. X        addstr("immortal.  You are now left to wither and die . . .\n");
  1344. X        more(3);
  1345. X        Player.p_brains = Player.p_level / 25.0;
  1346. X        Player.p_energy = Player.p_maxenergy /= 5.0;
  1347. X        Player.p_quksilver = Player.p_sword = 0.0;
  1348. X        Player.p_specialtype = SC_COUNCIL;
  1349. X        return;
  1350. X        }
  1351. X    else if (Player.p_ring.ring_inuse &&
  1352. X        (Player.p_ring.ring_type == R_DLREG || Player.p_ring.ring_type == R_NAZREG))
  1353. X        /* good ring in use - saved from death */
  1354. X        {
  1355. X        mvaddstr(4, 0, "Your ring saved you from death!\n");
  1356. X        refresh();
  1357. X        Player.p_ring.ring_type = R_NONE;
  1358. X        Player.p_energy = Player.p_maxenergy / 12.0 + 1.0;
  1359. X        if (Player.p_crowns > 0)
  1360. X        --Player.p_crowns;
  1361. X        return;
  1362. X        }
  1363. X    else if (Player.p_ring.ring_type == R_BAD
  1364. X        || Player.p_ring.ring_type == R_SPOILED)
  1365. X        /* bad ring in possession; name idiot after player */
  1366. X        {
  1367. X        mvaddstr(4, 0,
  1368. X        "Your ring has taken control of you and turned you into a monster!\n");
  1369. X        fseek(Monstfp, 13L * SZ_MONSTERSTRUCT, 0);
  1370. X        fread((char *) &Curmonster, SZ_MONSTERSTRUCT, 1, Monstfp);
  1371. X        strcpy(Curmonster.m_name, Player.p_name);
  1372. X        fseek(Monstfp, 13L * SZ_MONSTERSTRUCT, 0);
  1373. X        fwrite((char *) &Curmonster, SZ_MONSTERSTRUCT, 1, Monstfp);
  1374. X        fflush(Monstfp);
  1375. X        }
  1376. X    }
  1377. X
  1378. X    enterscore();        /* update score board */
  1379. X
  1380. X    /* put info in last dead file */
  1381. X    fp = fopen(Lastdead, "w");
  1382. X    fprintf(fp,"%s (%s, run by %s, level %.0f, killed by %s)",
  1383. X    Player.p_name, descrtype(&Player, TRUE),
  1384. X    Player.p_login, Player.p_level, how);
  1385. X    fclose(fp);
  1386. X
  1387. X    /* let other players know */
  1388. X    fp = fopen(Messfile, "w");
  1389. X    fprintf(fp, "%s was killed by %s.", Player.p_name, how);
  1390. X    fclose(fp);
  1391. X
  1392. X    freerecord(&Player, Fileloc);
  1393. X
  1394. X    clear();
  1395. X    move(10, 0);
  1396. X    addstr(deathmesg[(int) ROLL(0.0, (double) sizeof(deathmesg) / sizeof(char *))]);
  1397. X    addstr("Care to give it another try ? ");
  1398. X    ch = getanswer("NY", FALSE);
  1399. X
  1400. X    if (ch == 'Y')
  1401. X    {
  1402. X    cleanup(FALSE);
  1403. X    execl(Gameprog, "phantasia", "-s", (Wizard ? "-S": (char *) NULL), 0);
  1404. X    exit(0);
  1405. X    /*NOTREACHED*/
  1406. X    }
  1407. X
  1408. X    cleanup(TRUE);
  1409. X    /*NOTREACHED*/
  1410. X}
  1411. X/* */
  1412. X/************************************************************************
  1413. X/
  1414. X/ FUNCTION NAME: writerecord()
  1415. X/
  1416. X/ FUNCTION: update structure in player file
  1417. X/
  1418. X/ AUTHOR: E. A. Estes, 12/4/85
  1419. X/
  1420. X/ ARGUMENTS:
  1421. X/    struct player *playerp - pointer to structure to write out
  1422. X/    long place - location in file to updata
  1423. X/
  1424. X/ RETURN VALUE: none
  1425. X/
  1426. X/ MODULES CALLED: fseek(), fwrite(), fflush()
  1427. X/
  1428. X/ GLOBAL INPUTS: *Playersfp
  1429. X/
  1430. X/ GLOBAL OUTPUTS: none
  1431. X/
  1432. X/ DESCRIPTION:
  1433. X/    Update location in player file with given structure.
  1434. X/
  1435. X/************************************************************************/
  1436. X
  1437. Xwriterecord(playerp, place)
  1438. Xregister struct player    *playerp;
  1439. Xlong    place;
  1440. X{
  1441. X    fseek(Playersfp, place, 0);
  1442. X    fwrite((char *) playerp, SZ_PLAYERSTRUCT, 1, Playersfp);
  1443. X    fflush(Playersfp);
  1444. X}
  1445. X/* */
  1446. X/************************************************************************
  1447. X/
  1448. X/ FUNCTION NAME: explevel()
  1449. X/
  1450. X/ FUNCTION: calculate level based upon experience
  1451. X/
  1452. X/ AUTHOR: E. A. Estes, 12/4/85
  1453. X/
  1454. X/ ARGUMENTS:
  1455. X/    double experience - experience to calculate experience level from
  1456. X/
  1457. X/ RETURN VALUE: experience level
  1458. X/
  1459. X/ MODULES CALLED: pow(), floor()
  1460. X/
  1461. X/ GLOBAL INPUTS: none
  1462. X/
  1463. X/ GLOBAL OUTPUTS: none
  1464. X/
  1465. X/ DESCRIPTION: 
  1466. X/    Experience level is a geometric progression.  This has been finely
  1467. X/    tuned over the years, and probably should not be changed.
  1468. X/
  1469. X/************************************************************************/
  1470. X
  1471. Xdouble
  1472. Xexplevel(experience)
  1473. Xdouble    experience;
  1474. X{
  1475. X    if (experience < 1.1e7)
  1476. X    return(floor(pow((experience / 1000.0), 0.4875)));
  1477. X    else
  1478. X    return(floor(pow((experience / 1250.0), 0.4865)));
  1479. X}
  1480. X/* */
  1481. X/************************************************************************
  1482. X/
  1483. X/ FUNCTION NAME: truncstring()
  1484. X/
  1485. X/ FUNCTION: truncate trailing blanks off a string
  1486. X/
  1487. X/ AUTHOR: E. A. Estes, 12/4/85
  1488. X/
  1489. X/ ARGUMENTS: 
  1490. X/    char *string - pointer to null terminated string
  1491. X/
  1492. X/ RETURN VALUE: none
  1493. X/
  1494. X/ MODULES CALLED: strlen()
  1495. X/
  1496. X/ GLOBAL INPUTS: none
  1497. X/
  1498. X/ GLOBAL OUTPUTS: none
  1499. X/
  1500. X/ DESCRIPTION: 
  1501. X/    Put nul characters in place of spaces at the end of the string.
  1502. X/
  1503. X/************************************************************************/
  1504. X
  1505. Xtruncstring(string)
  1506. Xregister char    *string;
  1507. X{
  1508. Xregister int    length;        /* length of string */
  1509. X
  1510. X    length = strlen(string);
  1511. X    while (string[--length] == ' ')
  1512. X    string[length] = '\0';
  1513. X}
  1514. X/* */
  1515. X/************************************************************************
  1516. X/
  1517. X/ FUNCTION NAME: altercoordinates()
  1518. X/
  1519. X/ FUNCTION: Alter x, y coordinates and set/check location flags
  1520. X/
  1521. X/ AUTHOR: E. A. Estes, 12/16/85
  1522. X/
  1523. X/ ARGUMENTS: 
  1524. X/    double xnew, ynew - new x, y coordinates
  1525. X/    int operation - operation to perform with coordinates
  1526. X/
  1527. X/ RETURN VALUE: none
  1528. X/
  1529. X/ MODULES CALLED: fabs(), floor(), random(), distance()
  1530. X/
  1531. X/ GLOBAL INPUTS: Circle, Beyond, Player
  1532. X/
  1533. X/ GLOBAL OUTPUTS: Marsh, Circle, Beyond, Throne, Player, Changed
  1534. X/
  1535. X/ DESCRIPTION: 
  1536. X/    This module is called whenever the player's coordinates are altered.
  1537. X/    If the player is beyond the point of no return, he/she is forced
  1538. X/    to stay there.
  1539. X/
  1540. X/************************************************************************/
  1541. X
  1542. Xaltercoordinates(xnew, ynew, operation)
  1543. Xdouble    xnew;
  1544. Xdouble    ynew;
  1545. Xint    operation;
  1546. X{
  1547. X    switch (operation)
  1548. X    {
  1549. X    case A_FORCED:    /* move with no checks */
  1550. X        break;
  1551. X
  1552. X    case A_NEAR:    /* pick random coordinates near */
  1553. X        xnew = Player.p_x + ROLL(1.0, 5.0);
  1554. X        ynew = Player.p_y - ROLL(1.0, 5.0);
  1555. X        /* fall through for check */
  1556. X
  1557. X    case A_SPECIFIC:    /* just move player */
  1558. X        if (Beyond && fabs(xnew) < D_BEYOND && fabs(ynew) < D_BEYOND)
  1559. X        /*
  1560. X         * cannot move back from point of no return
  1561. X         * pick the largest coordinate to remain unchanged
  1562. X         */
  1563. X        {
  1564. X        if (fabs(xnew) > fabs(ynew))
  1565. X            xnew = SGN(Player.p_x) * MAX(fabs(Player.p_x), D_BEYOND);
  1566. X        else
  1567. X            ynew = SGN(Player.p_y) * MAX(fabs(Player.p_y), D_BEYOND);
  1568. X        }
  1569. X        break;
  1570. X
  1571. X    case A_FAR:    /* pick random coordinates far */
  1572. X        xnew = Player.p_x + SGN(Player.p_x) * ROLL(50 * Circle, 250 * Circle);
  1573. X        ynew = Player.p_y + SGN(Player.p_y) * ROLL(50 * Circle, 250 * Circle);
  1574. X        break;
  1575. X    }
  1576. X    
  1577. X    /* now set location flags and adjust coordinates */
  1578. X    Circle = CIRCLE(Player.p_x = floor(xnew), Player.p_y = floor(ynew));
  1579. X
  1580. X    /* set up flags based upon location */
  1581. X    Throne = Marsh = Beyond = FALSE;
  1582. X
  1583. X    if (Player.p_x == 0.0 && Player.p_y == 0.0)
  1584. X    Throne = TRUE;
  1585. X    else if (Circle < 35 && Circle >= 20)
  1586. X    Marsh = TRUE;
  1587. X    else if (MAX(fabs(Player.p_x), fabs(Player.p_y)) >= D_BEYOND)
  1588. X    Beyond = TRUE;
  1589. X
  1590. X    Changed = TRUE;
  1591. X}
  1592. X/* */
  1593. X/************************************************************************
  1594. X/
  1595. X/ FUNCTION NAME: readrecord()
  1596. X/
  1597. X/ FUNCTION: read a player structure from file
  1598. X/
  1599. X/ AUTHOR: E. A. Estes, 12/4/85
  1600. X/
  1601. X/ ARGUMENTS:
  1602. X/    struct player *playerp - pointer to structure to fill
  1603. X/    int loc - location of record to read
  1604. X/
  1605. X/ RETURN VALUE: none
  1606. X/
  1607. X/ MODULES CALLED: fread(), fseek()
  1608. X/
  1609. X/ GLOBAL INPUTS: *Playersfp
  1610. X/
  1611. X/ GLOBAL OUTPUTS: none
  1612. X/
  1613. X/ DESCRIPTION:
  1614. X/    Read structure information from player file.
  1615. X/
  1616. X/************************************************************************/
  1617. X
  1618. Xreadrecord(playerp, loc)
  1619. Xregister struct player    *playerp;
  1620. Xlong    loc;
  1621. X{
  1622. X    fseek(Playersfp, loc, 0);
  1623. X    fread((char *) playerp, SZ_PLAYERSTRUCT, 1, Playersfp);
  1624. X}
  1625. X/* */
  1626. X/************************************************************************
  1627. X/
  1628. X/ FUNCTION NAME: adjuststats()
  1629. X/
  1630. X/ FUNCTION: adjust player statistics
  1631. X/
  1632. X/ AUTHOR: E. A. Estes, 12/4/85
  1633. X/
  1634. X/ ARGUMENTS: none
  1635. X/
  1636. X/ RETURN VALUE: none
  1637. X/
  1638. X/ MODULES CALLED: death(), floor(), random(), explevel(), movelevel()
  1639. X/
  1640. X/ GLOBAL INPUTS: Player, *Statptr
  1641. X/
  1642. X/ GLOBAL OUTPUTS: Circle, Player, Timeout
  1643. X/
  1644. X/ DESCRIPTION:
  1645. X/    Handle adjustment and maximums on various player characteristics.
  1646. X/
  1647. X/************************************************************************/
  1648. X
  1649. Xadjuststats()
  1650. X{
  1651. Xdouble    dtemp;                /* for temporary calculations */
  1652. X
  1653. X    if (explevel(Player.p_experience) > Player.p_level)
  1654. X    /* move one or more levels */
  1655. X    {
  1656. X    movelevel();
  1657. X    if (Player.p_level > 5.0)
  1658. X        Timeout = TRUE;
  1659. X    }
  1660. X
  1661. X    if (Player.p_specialtype == SC_VALAR)
  1662. X    /* valar */
  1663. X    Circle = Player.p_level / 5.0;
  1664. X
  1665. X    /* calculate effective quickness */
  1666. X    dtemp = ((Player.p_gold + Player.p_gems / 2.0) - 1000.0) / Statptr->c_goldtote
  1667. X    - Player.p_level;;
  1668. X    dtemp = MAX(0.0, dtemp);        /* gold slows player down */
  1669. X    Player.p_speed = Player.p_quickness + Player.p_quksilver - dtemp;
  1670. X
  1671. X    /* calculate effective strength */
  1672. X    if (Player.p_poison > 0.0)
  1673. X    /* poison makes player weaker */
  1674. X    {
  1675. X    dtemp = 1.0 - Player.p_poison * Statptr->c_weakness / 800.0;
  1676. X    dtemp = MAX(0.1, dtemp);
  1677. X    }
  1678. X    else
  1679. X    dtemp = 1.0;
  1680. X    Player.p_might = dtemp *  Player.p_strength + Player.p_sword;
  1681. X
  1682. X    /* insure that important things are within limits */
  1683. X    Player.p_quksilver = MIN(99.0, Player.p_quksilver);
  1684. X    Player.p_mana = MIN(Player.p_mana,
  1685. X    Player.p_level * Statptr->c_maxmana + 1000.0);
  1686. X    Player.p_brains = MIN(Player.p_brains,
  1687. X    Player.p_level * Statptr->c_maxbrains + 200.0);
  1688. X    Player.p_charms = MIN(Player.p_charms, Player.p_level + 10.0);
  1689. X
  1690. X    /*
  1691. X     * some implementations have problems with floating point compare
  1692. X     * we work around it with this stuff
  1693. X     */
  1694. X    Player.p_gold = floor(Player.p_gold) + 0.1;
  1695. X    Player.p_gems = floor(Player.p_gems) + 0.1;
  1696. X    Player.p_mana = floor(Player.p_mana) + 0.1;
  1697. X
  1698. X    if (Player.p_ring.ring_type != R_NONE)
  1699. X    /* do ring things */
  1700. X    {
  1701. X    /* rest to max */
  1702. X    Player.p_energy = Player.p_maxenergy + Player.p_shield;
  1703. X
  1704. X        if (Player.p_ring.ring_duration <= 0)
  1705. X        /* clean up expired rings */
  1706. X        switch (Player.p_ring.ring_type)
  1707. X        {
  1708. X        case R_BAD:    /* ring drives player crazy */
  1709. X            Player.p_ring.ring_type = R_SPOILED;
  1710. X            Player.p_ring.ring_duration = (short) ROLL(10.0, 25.0);
  1711. X            break;
  1712. X
  1713. X        case R_NAZREG:    /* ring disappears */
  1714. X            Player.p_ring.ring_type = R_NONE;
  1715. X            break;
  1716. X
  1717. X        case R_SPOILED:    /* ring kills player */
  1718. X            death("A cursed ring");
  1719. X            break;
  1720. X
  1721. X        case R_DLREG:    /* this ring doesn't expire */
  1722. X            Player.p_ring.ring_duration = 0;
  1723. X            break;
  1724. X        }
  1725. X    }
  1726. X
  1727. X    if (Player.p_age / N_AGE > Player.p_degenerated)
  1728. X    /* age player slightly */
  1729. X    {
  1730. X    ++Player.p_degenerated;
  1731. X    if (Player.p_quickness > 23.0)
  1732. X        Player.p_quickness *= 0.99;
  1733. X    Player.p_strength *= 0.97;
  1734. X    Player.p_brains *= 0.95;
  1735. X    Player.p_magiclvl *= 0.97;
  1736. X    Player.p_maxenergy *= 0.95;
  1737. X    Player.p_quksilver *= 0.95;
  1738. X    Player.p_sword *= 0.93;
  1739. X    Player.p_shield *= 0.93;
  1740. X    }
  1741. X}
  1742. X/* */
  1743. X/************************************************************************
  1744. X/
  1745. X/ FUNCTION NAME: initplayer()
  1746. X/
  1747. X/ FUNCTION: initialize a character
  1748. X/
  1749. X/ AUTHOR: E. A. Estes, 12/4/85
  1750. X/
  1751. X/ ARGUMENTS:
  1752. X/    struct player *playerp - pointer to structure to init
  1753. X/
  1754. X/ RETURN VALUE: none
  1755. X/
  1756. X/ MODULES CALLED: floor(), random()
  1757. X/
  1758. X/ GLOBAL INPUTS: none
  1759. X/
  1760. X/ GLOBAL OUTPUTS: none
  1761. X/
  1762. X/ DESCRIPTION:
  1763. X/    Put a bunch of default values in the given structure.
  1764. X/
  1765. X/************************************************************************/
  1766. X
  1767. Xinitplayer(playerp)
  1768. Xregister struct  player   *playerp;
  1769. X{
  1770. X    playerp->p_experience =
  1771. X    playerp->p_level =
  1772. X    playerp->p_strength =
  1773. X    playerp->p_sword =
  1774. X    playerp->p_might =
  1775. X    playerp->p_energy =
  1776. X    playerp->p_maxenergy =
  1777. X    playerp->p_shield =
  1778. X    playerp->p_quickness =
  1779. X    playerp->p_quksilver =
  1780. X    playerp->p_speed =
  1781. X    playerp->p_magiclvl =
  1782. X    playerp->p_mana =
  1783. X    playerp->p_brains =
  1784. X    playerp->p_poison =
  1785. X    playerp->p_gems =
  1786. X    playerp->p_sin =
  1787. X    playerp->p_1scratch =
  1788. X    playerp->p_2scratch = 0.0;
  1789. X
  1790. X    playerp->p_gold = ROLL(50.0, 75.0) + 0.1;    /* give some gold */
  1791. X
  1792. X    playerp->p_x = ROLL(-125.0, 251.0);
  1793. X    playerp->p_y = ROLL(-125.0, 251.0);        /* give random x, y */
  1794. X
  1795. X    /* clear ring */
  1796. X    playerp->p_ring.ring_type = R_NONE;
  1797. X    playerp->p_ring.ring_duration = 0;
  1798. X    playerp->p_ring.ring_inuse = FALSE;
  1799. X
  1800. X    playerp->p_age = 0L;
  1801. X
  1802. X    playerp->p_degenerated = 1;            /* don't degenerate initially */
  1803. X
  1804. X    playerp->p_type = C_FIGHTER;        /* default */
  1805. X    playerp->p_specialtype = SC_NONE;
  1806. X    playerp->p_lives =
  1807. X    playerp->p_crowns = 
  1808. X    playerp->p_charms =
  1809. X    playerp->p_amulets =
  1810. X    playerp->p_holywater =
  1811. X    playerp->p_lastused = 0;
  1812. X    playerp->p_status = S_NOTUSED;
  1813. X    playerp->p_tampered = T_OFF;
  1814. X    playerp->p_istat = I_OFF;
  1815. X
  1816. X    playerp->p_palantir =
  1817. X    playerp->p_blessing =
  1818. X    playerp->p_virgin =
  1819. X    playerp->p_blindness = FALSE;
  1820. X
  1821. X    playerp->p_name[0] =
  1822. X    playerp->p_password[0] =
  1823. X    playerp->p_login[0] = '\0';
  1824. X}
  1825. X/* */
  1826. X/************************************************************************
  1827. X/
  1828. X/ FUNCTION NAME: readmessage()
  1829. X/
  1830. X/ FUNCTION: read message from other players
  1831. X/
  1832. X/ AUTHOR: E. A. Estes, 12/4/85
  1833. X/
  1834. X/ ARGUMENTS: none
  1835. X/
  1836. X/ RETURN VALUE: none
  1837. X/
  1838. X/ MODULES CALLED: fseek(), fgets(), wmove(), waddstr(), wclrtoeol()
  1839. X/
  1840. X/ GLOBAL INPUTS: *stdscr, Databuf[], *Messagefp
  1841. X/
  1842. X/ GLOBAL OUTPUTS: none
  1843. X/
  1844. X/ DESCRIPTION:
  1845. X/    If there is a message from other players, print it.
  1846. X/
  1847. X/************************************************************************/
  1848. X
  1849. Xreadmessage()
  1850. X{
  1851. X    move(3, 0);
  1852. X    clrtoeol();
  1853. X    fseek(Messagefp, 0L, 0);
  1854. X    if (fgets(Databuf, SZ_DATABUF, Messagefp) != NULL)
  1855. X    addstr(Databuf);
  1856. X}
  1857. X/* */
  1858. X/************************************************************************
  1859. X/
  1860. X/ FUNCTION NAME: error()
  1861. X/
  1862. X/ FUNCTION: process evironment error
  1863. X/
  1864. X/ AUTHOR: E. A. Estes, 12/4/85
  1865. X/
  1866. X/ ARGUMENTS:
  1867. X/    char *whichfile - pointer to name of file which caused error
  1868. X/
  1869. X/ RETURN VALUE: none
  1870. X/
  1871. X/ MODULES CALLED: wclear(), cleanup()
  1872. X/
  1873. X/ GLOBAL INPUTS: errno, *stdscr, printw(), printf(), Windows
  1874. X/
  1875. X/ GLOBAL OUTPUTS: none
  1876. X/
  1877. X/ DESCRIPTION:
  1878. X/    Print message about offending file, and exit.
  1879. X/
  1880. X/************************************************************************/
  1881. X
  1882. Xerror(whichfile)
  1883. Xchar    *whichfile;
  1884. X{
  1885. Xextern int errno;
  1886. Xextern printw(), printf();
  1887. Xint    (*funcp)();
  1888. X
  1889. X    if (Windows)
  1890. X    {
  1891. X    funcp = printw;
  1892. X    clear();
  1893. X    }
  1894. X    else
  1895. X    funcp = printf;
  1896. X
  1897. X    (*funcp)("An unrecoverable error has occurred reading %s.  (errno = %d)\n", whichfile, errno);
  1898. X    (*funcp)("Please run 'setup' to determine the problem.\n");
  1899. X    cleanup(TRUE);
  1900. X    /*NOTREACHED*/
  1901. X}
  1902. X/* */
  1903. X/************************************************************************
  1904. X/
  1905. X/ FUNCTION NAME: distance()
  1906. X/
  1907. X/ FUNCTION: calculate distance between two points
  1908. X/
  1909. X/ AUTHOR: E. A. Estes, 12/4/85
  1910. X/
  1911. X/ ARGUMENTS: 
  1912. X/    double x1, y1 - x, y coordinates of first point
  1913. X/    double x2, y2 - x, y coordinates of second point
  1914. X/
  1915. X/ RETURN VALUE: distance between the two points
  1916. X/
  1917. X/ MODULES CALLED: sqrt()
  1918. X/
  1919. X/ GLOBAL INPUTS: none
  1920. X/
  1921. X/ GLOBAL OUTPUTS: none
  1922. X/
  1923. X/ DESCRIPTION:
  1924. X/    This function is provided because someone's hypot() library function
  1925. X/    fails if x1 == x2 && y1 == y2.
  1926. X/
  1927. X/************************************************************************/
  1928. X
  1929. Xdouble
  1930. Xdistance(x1, x2, y1, y2)
  1931. Xdouble    x1, x2, y1, y2;
  1932. X{
  1933. Xdouble    deltax, deltay;
  1934. X
  1935. X    deltax = x1 - x2;
  1936. X    deltay = y1 - y2;
  1937. X    return(sqrt(deltax * deltax + deltay * deltay));
  1938. X}
  1939. X
  1940. X/* */
  1941. X/************************************************************************
  1942. X/
  1943. X/ FUNCTION NAME: ill_sig()
  1944. X/
  1945. X/ FUNCTION: exit upon trapping an illegal signal
  1946. X/
  1947. X/ AUTHOR: E. A. Estes, 12/4/85
  1948. X/
  1949. X/ ARGUMENTS:
  1950. X/    int whichsig - signal which occured to cause jump to here
  1951. X/
  1952. X/ RETURN VALUE: none
  1953. X/
  1954. X/ MODULES CALLED: wclear(), printw(), cleanup()
  1955. X/
  1956. X/ GLOBAL INPUTS: *stdscr
  1957. X/
  1958. X/ GLOBAL OUTPUTS: none
  1959. X/
  1960. X/ DESCRIPTION:
  1961. X/    When an illegal signal is caught, print a message, and cleanup.
  1962. X/
  1963. X/************************************************************************/
  1964. X
  1965. Xill_sig(whichsig)
  1966. Xint whichsig;
  1967. X{
  1968. X    clear();
  1969. X    printw("Error: caught signal # %d.\n", whichsig);
  1970. X    cleanup(TRUE);
  1971. X    /*NOTREACHED*/
  1972. X}
  1973. X/* */
  1974. X/************************************************************************
  1975. X/
  1976. X/ FUNCTION NAME: descrstatus()
  1977. X/
  1978. X/ FUNCTION: return a string describing the player status
  1979. X/
  1980. X/ AUTHOR: E. A. Estes, 3/3/86
  1981. X/
  1982. X/ ARGUMENTS:
  1983. X/    struct player playerp - pointer to player structure to describe
  1984. X/
  1985. X/ RETURN VALUE: string describing player's status
  1986. X/
  1987. X/ MODULES CALLED: none
  1988. X/
  1989. X/ GLOBAL INPUTS: none
  1990. X/
  1991. X/ GLOBAL OUTPUTS: none
  1992. X/
  1993. X/ DESCRIPTION:
  1994. X/    Return verbal description of player status.
  1995. X/    If player status is S_PLAYING, check for low energy and blindness.
  1996. X/
  1997. X/************************************************************************/
  1998. X
  1999. Xchar    *
  2000. Xdescrstatus(playerp)
  2001. Xregister struct player    *playerp;
  2002. X{
  2003. X    switch (playerp->p_status)
  2004. X    {
  2005. X    case S_PLAYING:
  2006. X        if (playerp->p_energy < 0.2 * (playerp->p_maxenergy + playerp->p_shield))
  2007. X        return("Low Energy");
  2008. X        else if (playerp->p_blindness)
  2009. X        return("Blind");
  2010. X        else
  2011. X        return("In game");
  2012. X
  2013. X    case S_CLOAKED:
  2014. X        return("Cloaked");
  2015. X
  2016. X    case S_INBATTLE:
  2017. X        return("In Battle");
  2018. X
  2019. X    case S_MONSTER:
  2020. X        return("Encounter");
  2021. X
  2022. X    case S_TRADING:
  2023. X        return("Trading");
  2024. X
  2025. X    case S_OFF:
  2026. X        return("Off");
  2027. X
  2028. X    case S_HUNGUP:
  2029. X        return("Hung up");
  2030. X
  2031. X    default:
  2032. X        return("");
  2033. X    }
  2034. X}
  2035. X/* */
  2036. X/************************************************************************
  2037. X/
  2038. X/ FUNCTION NAME: random()
  2039. X/
  2040. X/ FUNCTION: return a random floating point number from 0.0 < 1.0
  2041. X/
  2042. X/ AUTHOR: E. A. Estes, 2/7/86
  2043. X/
  2044. X/ ARGUMENTS: none
  2045. X/
  2046. X/ RETURN VALUE: none
  2047. X/
  2048. X/ MODULES CALLED: rand()
  2049. X/
  2050. X/ GLOBAL INPUTS: none
  2051. X/
  2052. X/ GLOBAL OUTPUTS: none
  2053. X/
  2054. X/ DESCRIPTION:
  2055. X/    Convert random integer from library routine into a floating
  2056. X/    point number, and divide by the largest possible random number.
  2057. X/    We mask large integers with 32767 to handle sites that return
  2058. X/    31 bit random integers.
  2059. X/
  2060. X/************************************************************************/
  2061. X
  2062. Xdouble
  2063. Xrandom()
  2064. X{
  2065. X    if (sizeof(int) != 2)
  2066. X    /* use only low bits */
  2067. X    return((double) (rand() & 0x7fff) / 32768.0);
  2068. X    else
  2069. X    return((double) rand() / 32768.0);
  2070. X}
  2071. X/* */
  2072. X/************************************************************************
  2073. X/
  2074. X/ FUNCTION NAME: collecttaxes()
  2075. X/
  2076. X/ FUNCTION: collect taxes from current player
  2077. X/
  2078. X/ AUTHOR: E. A. Estes, 2/7/86
  2079. X/
  2080. X/ ARGUMENTS:
  2081. X/    double gold - amount of gold to tax
  2082. X/    double gems - amount of gems to tax
  2083. X/
  2084. X/ RETURN VALUE: none
  2085. X/
  2086. X/ MODULES CALLED: fread(), fseek(), fopen(), floor(), fwrite(), fclose()
  2087. X/
  2088. X/ GLOBAL INPUTS: Player, Goldfile[]
  2089. X/
  2090. X/ GLOBAL OUTPUTS: Player
  2091. X/
  2092. X/ DESCRIPTION:
  2093. X/    Pay taxes on gold and gems.  If the player does not have enough
  2094. X/    gold to pay taxes on the added gems, convert some gems to gold.
  2095. X/    Add taxes to tax data base; add remaining gold and gems to
  2096. X/    player's cache.
  2097. X/
  2098. X/************************************************************************/
  2099. X
  2100. Xcollecttaxes(gold, gems)
  2101. Xdouble    gold;
  2102. Xdouble    gems;
  2103. X{
  2104. XFILE    *fp;        /* to update Goldfile */
  2105. Xdouble    dtemp;        /* for temporary calculations */
  2106. Xdouble    taxes;        /* tax liability */
  2107. X
  2108. X    /* add to cache */
  2109. X    Player.p_gold += gold;
  2110. X    Player.p_gems += gems;
  2111. X
  2112. X    /* calculate tax liability */
  2113. X    taxes = N_TAXAMOUNT / 100.0 * (N_GEMVALUE * gems + gold);
  2114. X
  2115. X    if (Player.p_gold < taxes)
  2116. X    /* not enough gold to pay taxes, must convert some gems to gold */
  2117. X    {
  2118. X    dtemp = floor(taxes / N_GEMVALUE + 1.0); /* number of gems to convert */
  2119. X
  2120. X    if (Player.p_gems >= dtemp)
  2121. X        /* player has enough to convert */
  2122. X        {
  2123. X        Player.p_gems -= dtemp;
  2124. X        Player.p_gold += dtemp * N_GEMVALUE;
  2125. X        }
  2126. X    else
  2127. X        /* take everything; this should never happen */
  2128. X        {
  2129. X        Player.p_gold += Player.p_gems * N_GEMVALUE;
  2130. X        Player.p_gems = 0.0;
  2131. X        taxes = Player.p_gold;
  2132. X        }
  2133. X    }
  2134. X
  2135. X    Player.p_gold -= taxes;
  2136. X
  2137. X    if ((fp = fopen(Goldfile, "r+")) != NULL)
  2138. X    /* update taxes */
  2139. X    {
  2140. X    dtemp = 0.0;
  2141. X    fread((char *) &dtemp, sizeof(double), 1, fp);
  2142. X    dtemp += floor(taxes);
  2143. X    fseek(fp, 0L, 0);
  2144. X    fwrite((char *) &dtemp, sizeof(double), 1, fp);
  2145. X    fclose(fp);
  2146. X    }
  2147. X}
  2148. !EOR!
  2149. echo x - oldplayer.h
  2150. sed 's/^X//' > oldplayer.h << '!EOR!'
  2151. X/*
  2152. X * oldplayer.h - old player structure
  2153. X */
  2154. X
  2155. Xstruct    oldplayer            /* player statistics */
  2156. X    {
  2157. X    char    o_name[21];    /* name */
  2158. X    char    o_password[9];    /* password */
  2159. X    char    o_login[10];    /* login */
  2160. X    double    o_x;            /* x coord */
  2161. X    double    o_y;            /* y coord */
  2162. X    double    o_experience;    /* experience */
  2163. X    int        o_level;        /* level */
  2164. X    short    o_quickness;    /* quickness */
  2165. X    double    o_strength;    /* strength */
  2166. X    double    o_sin;        /* sin */
  2167. X    double    o_mana;        /* mana */
  2168. X    double    o_gold;        /* gold */
  2169. X    double    o_energy;    /* energy */
  2170. X    double    o_maxenergy;    /* maximum energy */
  2171. X    double    o_magiclvl;    /* magic level */
  2172. X    double    o_brains;    /* brains */
  2173. X    short    o_crowns;    /* crowns */
  2174. X    struct
  2175. X    {
  2176. X    short    ring_type;    /* type of ring */
  2177. X    short    ring_duration;    /* duration of ring */
  2178. X    }    o_ring;            /* ring stuff */
  2179. X    bool    o_palantir;    /* palantir */
  2180. X    double    o_poison;    /* poison */
  2181. X    short    o_holywater;       /* holy water */
  2182. X    short    o_amulets;    /* amulets */
  2183. X    bool    o_blessing;    /* blessing */
  2184. X    short    o_charms;    /* charms */
  2185. X    double    o_gems;        /* gems */
  2186. X    short    o_quksilver;    /* quicksilver */
  2187. X    double    o_sword;    /* sword */
  2188. X    double    o_shield;    /* shield */
  2189. X    short    o_type;        /* character type */
  2190. X    bool    o_virgin;    /* virgin */
  2191. X    short    o_lastused;    /* day of year last used */
  2192. X    short    o_status;    /* playing, cloaked, etc. */
  2193. X    short    o_tampered;    /* decree'd, etc. flag */
  2194. X    double    o_1scratch,
  2195. X        o_2scratch;    /* variables used for decree, player battle */
  2196. X    bool    o_blindness;    /* blindness */
  2197. X    int        o_notused;       /* not used */
  2198. X    long    o_age;        /* age in seconds */
  2199. X    short    o_degenerated;    /* age/2500 last degenerated */
  2200. X    short    o_istat;    /* used for inter-terminal battle */
  2201. X#ifdef PHANTPLUS
  2202. X    short    o_lives;
  2203. X#endif
  2204. X    };
  2205. !EOR!
  2206.  
  2207.  
  2208.